#include "MovimientosModule.h"
#include "QScrollBar"

extern QSqlDatabase enjoylifedb;
extern MovimientoSqlTableModel *movimientos_model;
extern QTableView *movimientos_view;
extern QLineEdit *saldo_line1;

//
MovimientosModule::MovimientosModule(QWidget *parent) :
    QMainWindow(parent)
{
    moviminetos_toolbar = new CustomModulesToolbar(this);
    AltaMovimientoToolBar();
    BajaMovimientoToolBar();
    ModificacionMovimientoToolBar();
    UpdateMovimientosListToolBar();
    ABMPersonaToolBar();
    ABMConceptoToolBar();
    addToolBar(moviminetos_toolbar);

    movimientos_model = new MovimientoSqlTableModel(this,enjoylifedb);
    movimientos_model->setTable("movimiento");
    movimientos_model->setEditStrategy(MovimientoSqlTableModel::OnFieldChange);

    movimientos_view = new QTableView(this);
    setCentralWidget(movimientos_view);

    QWidget* widget_main = new QWidget();
    QWidget* widget_derecho = new QWidget();

    QGridLayout *grid_lay = new QGridLayout();
    QGridLayout *grid_derecho = new QGridLayout();

    QGroupBox *group_father = new QGroupBox("Saldos",this);
    form_saldos = new QFormLayout;

    QLabel *saldo_label1 = new QLabel("Saldo Mes Actual $",0);
    saldo_label1->setFixedSize(190,20);
    saldo_label1->setAlignment(Qt::AlignCenter);
    saldo_label1->setStyleSheet("background-color: rgb(13, 200, 35); font: 11pt \"Helvetica57-Condensed\";border-style: solid");
    form_saldos->addRow(saldo_label1);

    saldo_line1 = new QLineEdit(this);
    saldo_line1->setFixedSize(190,80);
    saldo_line1->setEnabled(false);
    saldo_line1->setAlignment(Qt::AlignCenter);
    saldo_line1->setStyleSheet("background-color: rgb(0, 139, 56);color: rgb(255, 255, 255);font: 34pt \"Helvetica57-Condensed\";border-style: solid");
//    saldo_line1->setText("0");
    form_saldos->addRow(saldo_line1);

    QLabel *separador = new QLabel("",0);
    separador->setFixedSize(190,20);
    separador->setAlignment(Qt::AlignCenter);
    separador->setStyleSheet("background-color: rgb(255,255,255)");
    form_saldos->addRow(separador);

    QLabel *saldo_label2 = new QLabel("Saldo desde...",0);
    saldo_label2->setFixedSize(190,20);
    saldo_label2->setAlignment(Qt::AlignCenter);
    saldo_label2->setStyleSheet("background-color: rgb(13, 200, 35); font: 11pt \"Helvetica57-Condensed\";border-style: solid");
    form_saldos->addRow(saldo_label2);

    fecha1_saldo = new QDateEdit(this);
    fecha1_saldo->setFixedSize(190,30);
    fecha1_saldo->setEnabled(true);
    fecha1_saldo->setStyleSheet("background-color: rgb(200, 200, 200);color: rgb(0, 0, 0);font: 15pt \"Helvetica57-Condensed\";border-style: solid");
    QDate *date1;
    fecha1_saldo->setDate(date1->currentDate());
    form_saldos->addRow(fecha1_saldo);

    QLabel *saldo_label3 = new QLabel("Saldo hasta...",0);
    saldo_label3->setFixedSize(190,20);
    saldo_label3->setAlignment(Qt::AlignCenter);
    saldo_label3->setStyleSheet("background-color: rgb(13, 200, 35); font: 11pt \"Helvetica57-Condensed\";border-style: solid");
    form_saldos->addRow(saldo_label3);

    fecha2_saldo = new QDateEdit(this);
    fecha2_saldo->setFixedSize(190,30);
    fecha2_saldo->setEnabled(true);
    fecha2_saldo->setStyleSheet("background-color: rgb(200, 200, 200);color: rgb(0, 0, 0);font: 15pt \"Helvetica57-Condensed\";border-style: solid");
    QDate *date2;
    fecha2_saldo->setDate(date2->currentDate());
    form_saldos->addRow(fecha2_saldo);

    saldo_line2 = new QLineEdit(this);
    saldo_line2->setFixedSize(190,55);
    saldo_line2->setEnabled(false);
    saldo_line2->setAlignment(Qt::AlignCenter);
    saldo_line2->setStyleSheet("background-color: rgb(0, 139, 56);color: rgb(255, 255, 255);font: 24pt \"Helvetica57-Condensed\";border-style: solid");
    saldo_line2->setText("0.00");
    form_saldos->addRow(saldo_line2);

    //
    QPixmap SITIimage("://Images/SITI-Soft_Logo.png");
    QLabel *SITILabel = new QLabel("",0);
    SITILabel->setPixmap(SITIimage);
    SITILabel->setFixedHeight(225);
    SITILabel->setAlignment(Qt::AlignCenter);

    group_father->setLayout(form_saldos);
    group_father->setFixedWidth(210);

    grid_derecho->addWidget(group_father,0,0);
    grid_derecho->addWidget(SITILabel,1,0);
    widget_derecho->setFixedWidth(220);
    widget_derecho->setLayout(grid_derecho);

    grid_lay->addWidget(movimientos_view,0,0);
    grid_lay->addWidget(widget_derecho,0,1);

    widget_main->setLayout(grid_lay);
    setCentralWidget(widget_main);

    UpdateMovimientosListBtn();

    // Doble click sobre un movimiento abre la edición.
    connect(movimientos_view,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(ModificacionMovimientoBtn()));
    // Al cambiar las fecha se recalcula el saldo.
    connect(fecha1_saldo,SIGNAL(dateChanged(QDate)),this,SLOT(SaldoEntreFechas()));
    connect(fecha2_saldo,SIGNAL(dateChanged(QDate)),this,SLOT(SaldoEntreFechas()));

    // Definición de acceso directo para agregar un registro mediante la combinacion de teclas "Ctrl + A".
    QShortcut* shortcutAlta = new QShortcut(QKeySequence("Ctrl+A"), movimientos_view);
    connect(shortcutAlta, SIGNAL(activated()), this, SLOT(AltaMovimientoBtn()));
    // Definición de acceso directo para borrar un registro mediante la tecla "Supr".
    QShortcut* shortcutBaja = new QShortcut(QKeySequence(QKeySequence::Delete), movimientos_view);
    connect(shortcutBaja, SIGNAL(activated()), this, SLOT(BajaMovimientoBtn()));
    // Definición de acceso directo para modificar un registro mediante la combinacion de teclas "Ctrl + M".
    QShortcut* shortcutModif = new QShortcut(QKeySequence("Ctrl+M"), movimientos_view);
    connect(shortcutModif, SIGNAL(activated()), this, SLOT(ModificacionMovimientoBtn()));
    // Definición de acceso directo para actualizr la lista mediante la combinacion de teclas "Ctrl + U".
    QShortcut* shortcutActualizar = new QShortcut(QKeySequence("Ctrl+U"), this);
    connect(shortcutActualizar, SIGNAL(activated()), this, SLOT(UpdateMovimientosListBtn()));
    // Definición de acceso directo para abrir abm de conceptos mediante la combinacion de teclas "Ctrl + C".
    QShortcut* shortcutImprimir = new QShortcut(QKeySequence("Ctrl+C"), this);
    connect(shortcutImprimir, SIGNAL(activated()), this, SLOT(ABMConceptoBtn()));
    // Definición de acceso directo para abrir abm de personas mediante la combinacion de teclas "Ctrl + P".
    QShortcut* shortcutImprimir2 = new QShortcut(QKeySequence("Ctrl+P"), this);
    connect(shortcutImprimir2, SIGNAL(activated()), this, SLOT(ABMPersonaBtn()));
}

/*
 * Icono: Alta de movimientos.
 */
void MovimientosModule::AltaMovimientoToolBar()
{
    action_altaMovimiento = new QAction("Alta Moviemiento",this);
    action_altaMovimiento->setIcon(QIcon("://Icons/BarraHerramientas/alta48.png"));
    action_altaMovimiento->setIconText("Alta Movimiento");
    action_altaMovimiento->setToolTip("Agrega un Moviemiento");

    connect(action_altaMovimiento,SIGNAL(triggered()),this,SLOT(AltaMovimientoBtn()));

    moviminetos_toolbar->addAction(action_altaMovimiento);
}

/*
 * Icono: Baja de Movimiento.
 */
void MovimientosModule::BajaMovimientoToolBar()
{
    action_bajaMovimiento = new QAction("Baja Moviemiento",this);
    action_bajaMovimiento->setIcon(QIcon("://Icons/BarraHerramientas/baja48.png"));
    action_bajaMovimiento->setIconText("Baja Movimiento");
    action_bajaMovimiento->setToolTip("Elimina un Moviemiento");

    connect(action_bajaMovimiento,SIGNAL(triggered()),this,SLOT(BajaMovimientoBtn()));

    moviminetos_toolbar->addAction(action_bajaMovimiento);
}

/*
 * Icono: Modificación de Movimiento.
 */
void MovimientosModule::ModificacionMovimientoToolBar()
{
    action_modificacionMovimiento = new QAction("Modificar Moviemiento",this);
    action_modificacionMovimiento->setIcon(QIcon("://Icons/BarraHerramientas/modificar48.png"));
    action_modificacionMovimiento->setIconText("Modificar Movimiento");
    action_modificacionMovimiento->setToolTip("Modifica un Moviemiento");

    connect(action_modificacionMovimiento,SIGNAL(triggered()),this,SLOT(ModificacionMovimientoBtn()));

    moviminetos_toolbar->addAction(action_modificacionMovimiento);
}

/*
 * Icono: Actualizar lista de movimientos.
 */
void MovimientosModule::UpdateMovimientosListToolBar()
{
    action_updateMovimientosList = new QAction("Actualizar Lista Mov.",this);
    action_updateMovimientosList->setIcon(QIcon("://Icons/BarraHerramientas/actualizar48.png"));
    action_updateMovimientosList->setIconText("Actualizar Lista Mov.");
    action_updateMovimientosList->setToolTip("Actualiza la lista de movimientos");

    connect(action_updateMovimientosList,SIGNAL(triggered()),this,SLOT(UpdateMovimientosListBtn()));

    moviminetos_toolbar->addSeparator();
    moviminetos_toolbar->addAction(action_updateMovimientosList);
    moviminetos_toolbar->addSeparator();
}

/*
 * Icono: ABM Persona.
 */
void MovimientosModule::ABMPersonaToolBar()
{
    action_abmPersona = new QAction("ABM Persona",this);
    action_abmPersona->setIcon(QIcon("://Icons/BarraHerramientas/abmPersonas48.png"));
    action_abmPersona->setIconText("ABM Persona");
    action_abmPersona->setToolTip("Administra Personas");

    connect(action_abmPersona,SIGNAL(triggered()),this,SLOT(ABMPersonaBtn()));

    moviminetos_toolbar->addAction(action_abmPersona);
}

/*
 * Icono: ABM Concepto.
 */
void MovimientosModule::ABMConceptoToolBar()
{
    action_abmConcepto = new QAction("ABM Concepto", this);
    action_abmConcepto->setIcon(QIcon("://Icons/BarraHerramientas/abmConceptos48.png"));
    action_abmConcepto->setIconText("ABM Concepto");
    action_abmConcepto->setToolTip("Administra Conceptos");
    connect(action_abmConcepto,SIGNAL(triggered()),this,SLOT(ABMConceptoBtn()));

    moviminetos_toolbar->addAction(action_abmConcepto);
}

/*
 * Acción del boton: ejecuta la ventana para realizar altas de movimientos.
 */
void MovimientosModule::AltaMovimientoBtn()
{
    AltaMovimiento *alta_mov = new AltaMovimiento();
    alta_mov->show();
    UpdateMovimientosListBtn();
    CorrectViewOfModel();
}

/*
 * Acción del boton: se realiza una baja de moviemitos.
 */
void MovimientosModule::BajaMovimientoBtn()
{
    QModelIndexList selection;
    if (!(movimientos_view->currentIndex().row() == -1)) {
        selection.append(movimientos_view->currentIndex());
    }

    if (!selection.empty()) {
        QModelIndex idIndex = selection.first();
        QString rs = idIndex.sibling(idIndex.row(), 1).data().toString();
        QString moneda = idIndex.sibling(idIndex.row(), 4).data().toString();
        QString idMoneda = idIndex.sibling(idIndex.row(), 5).data().toString();
        QString idCtaCte = idIndex.sibling(idIndex.row(), 8).data().toString();

        if (moneda == "Cheque") {
            QMessageBox::information(this,"AVISO!", tr("El Movimineto que desea a eliminar está asociado a un Cheque. "
                                                       "Realice las acciones correspondientes, desde el Módulo Cheques, para el Cheque Nro.: '%1'.").arg(idMoneda),
                    QMessageBox::Ok);
            return;
        }
        if (!idCtaCte.isEmpty()) {
            QMessageBox::information(this,"AVISO!", tr("El Movimineto que desea a eliminar está asociado a una Cuenta Corriente. "
                                                       "Realice las acciones correspondientes, desde el Módulo Cuenta Corriente, para Cuenta Nro.: '%1'.").arg(idCtaCte),
                    QMessageBox::Ok);
            return;
        }

        QMessageBox::StandardButton button;
        button = QMessageBox::question(this, tr("Eleminar Movimiento"),
                                       tr("¿Está seguro que quiere "
                                          "eliminar el movimiento '%1'?").arg(rs),
                                       QMessageBox::Yes | QMessageBox::No);

        if (button == QMessageBox::Yes) {
            // Se elimina el movimiento seleccionado de la tabla movimiento
            enjoylifedb.transaction();
            if (!movimientos_model->removeRow(idIndex.row())) {
                QMessageBox::critical(this,"Error!", "No se pudo eliminar el movimiento, vuelva a intentarlo.");
                enjoylifedb.rollback();
                return;
            }
            enjoylifedb.commit();
            QMessageBox::information(this,"Exito!", "El movimiento fue eliminado correctamente.",
                                     QMessageBox::Ok);
        }
    }
    // Se actualiza listado de clientes.
    UpdateMovimientosListBtn();
    CorrectViewOfModel();
}

/*
 * Acción del boton: ejecuta la ventana para modificar un moviemiento.
 */
void MovimientosModule::ModificacionMovimientoBtn()
{
    // Se controla para el caso que no existan movimientos cargados.
    if (movimientos_model->rowCount() == 0) {
        QMessageBox::information(this,"Información!","No hay movimientos disponibles.");
        return;
    }

    int selection = -1;
    if (!(movimientos_view->currentIndex().row() == -1)) {
        selection = movimientos_view->currentIndex().row();
    }

    if (!(selection == -1)) {
        enjoylifedb.transaction();

        ModificacionMovimiento *modif_mov_form = new ModificacionMovimiento();
        modif_mov_form->GetMovimientoInfo(selection);
        modif_mov_form->show();

        enjoylifedb.commit();
        UpdateMovimientosListBtn();
        CorrectViewOfModel();
    } else {
        QMessageBox::warning(this, tr("Modificar Movimiento"),
                             tr("La operación no se puede concretar."
                                "\nNingún Movimiento ha sido seleccionado."));
    }
}

/*
 * Acción del boton: Ejecuta la ventana para administrar las personas.
 */
void MovimientosModule::ABMPersonaBtn()
{
    ABMPersona *abm_persona = new ABMPersona();
    abm_persona->show();
    CorrectViewOfModel();
}

/*
 * Acción del boton: Ejecuta la ventana para administrar los conceptos.
 */
void MovimientosModule::ABMConceptoBtn()
{
    ABMConcepto *abm_concepto = new ABMConcepto();
    abm_concepto->show();
    CorrectViewOfModel();
}

/*
 * Acción del boton: Actualiza la lista de moviemientos.
 */
void MovimientosModule::UpdateMovimientosListBtn()
{
    QDate date;
    date.setDate(date.currentDate().year(),date.currentDate().month(),date.currentDate().day());
    QString formatYear = "yyyy";
    QString formatMonth = "MM";
    QString anio, mes;
    anio = date.toString(formatYear);
    mes = date.toString(formatMonth);

    QString filtroMov;
    filtroMov = "date_part('year', fecha_mov) = '" + anio + "'";
    filtroMov = filtroMov + " and date_part('month', fecha_mov) <= '" + mes + "'";
    enjoylifedb.transaction();
    movimientos_model->setTable("movimiento");
    movimientos_model->filter().clear();
    movimientos_model->setFilter(filtroMov);
    if (!(movimientos_model->select())) {
        QMessageBox::critical(this,"Error!", "No se pudieron recuperar los registros, intentelo nuevamente más tarde.");
        enjoylifedb.rollback();
        return;
    }
    enjoylifedb.commit();
    saldo_line2->setText("0.00");
    CorrectViewOfModel();
    CalcularSaldoMensual();
}

/*
 * Acomoda la vista del modulo Movimientos.
 */
void MovimientosModule::CorrectViewOfModel()
{
    movimientos_model->setHeaderData(1,Qt::Horizontal,"Fecha");
    movimientos_model->setHeaderData(2,Qt::Horizontal,"Persona");
    movimientos_model->setHeaderData(3,Qt::Horizontal,"Concepto");
    movimientos_model->setHeaderData(4,Qt::Horizontal,"Tipo Moneda");
    movimientos_model->setHeaderData(6,Qt::Horizontal,"Cobro");
    movimientos_model->setHeaderData(7,Qt::Horizontal,"Pago");

    movimientos_view->setModel(movimientos_model);
    movimientos_view->setCornerButtonEnabled(true);
    movimientos_view->setAlternatingRowColors(true);
    movimientos_view->setGridStyle(Qt::SolidLine);
    movimientos_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
    movimientos_view->setWordWrap(true);
    movimientos_view->sortByColumn(1,Qt::SortOrder());
    movimientos_view->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    movimientos_view->hideColumn(0);
    movimientos_view->hideColumn(5);
    movimientos_view->hideColumn(8);
    movimientos_view->scrollToBottom();
}

/*
 *
 */
void MovimientosModule::CalcularSaldoMensual()
{
    QDate fechaCte;
    fechaCte.setDate(fechaCte.currentDate().year(), fechaCte.currentDate().month(), fechaCte.currentDate().day());

    QString formatoAnioCte = "yyyy";
    QString formatoMesCte = "MM";
    QString formatoDiaCte = "dd";
    QString anioCte, mesCte, diaCte, anioViejo;
    anioCte = fechaCte.toString(formatoAnioCte);
    anioViejo =
    mesCte = fechaCte.toString(formatoMesCte);
    diaCte = fechaCte.toString(formatoDiaCte);

    QString filtroMov;
    filtroMov = "date_part('year', fecha_mov) = '" + anioCte + "'";
//    filtroMov = filtroMov + " and date_part('month', fecha_mov) = '" + mesCte + "'";
//    filtroMov = filtroMov + " and date_part('day', fecha_mov) = '" + diaCte + "'";

    enjoylifedb.transaction();
    QSqlQuery *query = new QSqlQuery(enjoylifedb);
    QString stm = "select sum(debe) as sumDebe, sum(haber) as sumHaber from movimiento where " + filtroMov;
    if (! query->exec(stm)) {
        QMessageBox::critical(this,"Error!", "No se pudo recuperar los datos necesarios para calcular el saldo actual, "
                              "intentelo nuevamente || " + query->lastError().text());
        enjoylifedb.rollback();
        return;
    }

    double sumDebe, sumHaber;
    while (query->next()) {
        if (query->last()) {
            sumDebe = query->value(query->record().indexOf("sumDebe")).toDouble();
            sumHaber = query->value(query->record().indexOf("sumHaber")).toDouble();
        }
    }
    QVariant val = sumDebe - sumHaber;
    const int precision = 2;
    saldo_line1->setText(QString("%1").arg(val.toDouble(), 0, 'f', precision));

    enjoylifedb.commit();
}

/*
 * Cañcula el saldo entre dos fechas seleccionadas.
 */
void MovimientosModule::SaldoEntreFechas()
{
    QString fecha1, fecha2;

    QString formatYear1 = "yyyy";
    QString formatMonth1 = "MM";
    QString formatDay1 = "dd";
    QString anio1, mes1, dia1;
    anio1 = fecha1_saldo->date().toString(formatYear1);
    mes1 = fecha1_saldo->date().toString(formatMonth1);
    dia1 = fecha1_saldo->date().toString(formatDay1);

    fecha1.append(anio1).append(mes1).append(dia1);

    QString formatYear2 = "yyyy";
    QString formatMonth2 = "MM";
    QString formatDay2 = "dd";
    QString anio2, mes2, dia2;
    anio2 = fecha2_saldo->date().toString(formatYear2);
    mes2 = fecha2_saldo->date().toString(formatMonth2);
    dia2 = fecha2_saldo->date().toString(formatDay2);

    fecha2.append(anio2).append(mes2).append(dia2);

    enjoylifedb.transaction();
    QString filtroMov3;
    filtroMov3.append("fecha_mov BETWEEN '").append(fecha1).append("' and '").append(fecha2).append("'");
    movimientos_model->setTable("movimiento");
    movimientos_model->filter().clear();
    movimientos_model->setFilter(filtroMov3);
    if (!(movimientos_model->select())) {
        QMessageBox::critical(this,"Error!", "No se pudieron recuperar los registros, intentelo nuevamente más tarde.");
        enjoylifedb.rollback();
        return;
    }
    CorrectViewOfModel();

    QSqlQuery *query = new QSqlQuery(enjoylifedb);
    QString stm = "select sum(debe) as sumDebe, sum(haber) as sumHaber from movimiento where fecha_mov BETWEEN '" + fecha1 + "' and '" + fecha2 + "'";
    if (! query->exec(stm)) {
        QMessageBox::critical(this,"Error!", "No se pudo recuperar los datos necesarios para calcular el saldo..., "
                              "intentelo nuevamente || " + query->lastError().text());
        enjoylifedb.rollback();
        return;
    }

    double sumDebe, sumHaber;
    while (query->next()) {
        if (query->last()) {
            sumDebe = query->value(query->record().indexOf("sumDebe")).toDouble();
            sumHaber = query->value(query->record().indexOf("sumHaber")).toDouble();
        }
    }
    QVariant val = sumDebe - sumHaber;
    const int precision = 2;
    saldo_line2->setText(QString("%1").arg(val.toDouble(), 0, 'f', precision));
    enjoylifedb.commit();
}
